package blueq.dao.impl;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import blueq.dao.IBaseDao;


/**
 * 数据库访问基本接口，方法实现在BaseDaoImpl.java中
 * @version 1.1
 * @author 张帆
 */
public class BaseDaoImpl extends HibernateDaoSupport implements IBaseDao {
	// private static Logger log = Logger.getLogger(BaseDaoImpl.class);

	@SuppressWarnings("unchecked")
	public <T> List<T> findByHql(String queryString, Object... values)
	        throws HibernateException {
		return this.getHibernateTemplate().find(queryString, values);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see eblog.dao.impl.BaseDao#findByHql(java.lang.String, java.lang.Object)
	 */
	@SuppressWarnings("unchecked")
	public <T> List<T> findByHql(String queryString, Object value) {
		return this.getHibernateTemplate().find(queryString, value);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see eblog.dao.impl.BaseDao#findByExample(java.lang.Object)
	 */
	@SuppressWarnings("unchecked")
	public <T> List<T> findByExample(Object exampleEntity)
	        throws HibernateException {
		return getHibernateTemplate().findByExample(exampleEntity);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see eblog.dao.impl.BaseDao#findBySql(java.lang.String)
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public <T> List<T> findBySql(final String sql) {
		return (List<T>) getHibernateTemplate().execute(
		        new HibernateCallback() {
			        public Object doInHibernate(Session session)
			                throws HibernateException, SQLException {
				        Query query = session.createSQLQuery(sql);
				        return query.list();
			        }
		        });
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see eblog.dao.impl.BaseDao#findBySql(java.lang.String,
	 * java.lang.String[], java.lang.Object[])
	 */
	@SuppressWarnings("unchecked")
	public <T> List<T> findBySql(final String sql, final String[] paramNames,
	        final Object[] values) {
		return (List<T>) getHibernateTemplate().execute(
		        new HibernateCallback() {
			        public Object doInHibernate(Session session)
			                throws HibernateException, SQLException {
				        Query query = session.createSQLQuery(sql);
				        if (paramNames != null && values != null) {

					        if (paramNames.length != values.length) {
						        throw new IllegalArgumentException(
						                "Length of paramNames array must match length of values array");
					        }

					        for (int i = 0; i < values.length; i++) {
						        String paramName = paramNames[i];
						        Object value = values[i];

						        if (value instanceof Collection) {
							        query.setParameterList(paramName,
							                (Collection) value);
						        } else if (value instanceof Object[]) {
							        query.setParameterList(paramName,
							                (Object[]) value);
						        } else {
							        query.setParameter(paramName, value);
						        }
					        }
				        }
				        return query.list();
			        }
		        });
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see eblog.dao.impl.BaseDao#deleteObject(java.lang.Object)
	 */
	public void deleteObject(Object obj) throws HibernateException {
		this.getHibernateTemplate().delete(obj);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see eblog.dao.impl.BaseDao#findByHql(java.lang.String)
	 */
	@SuppressWarnings("unchecked")
	public <T> List<T> findByHql(String hql) {
		return getHibernateTemplate().find(hql);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see eblog.dao.impl.BaseDao#deleteObjectById(java.lang.Class,
	 * java.io.Serializable)
	 */
	public <T> void deleteObjectById(Class<T> class1, Serializable serializable) {
		try {
			getHibernateTemplate().delete(getObjectById(class1, serializable));
			getHibernateTemplate().flush();
		} catch (DataAccessException e) {
			e.printStackTrace();
		} catch (HibernateException e) {
			// log.debug("deleteObjectById occur error!");
			e.printStackTrace();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see eblog.dao.impl.BaseDao#insertBySql(java.lang.String)
	 */
	public Integer insertBySql(final String sql) {
		return (Integer) getHibernateTemplate().execute(
		        new HibernateCallback<Object>() {
			        public Object doInHibernate(Session session)
			                throws HibernateException, SQLException {
				        int query = session.createSQLQuery(sql).executeUpdate();
				        return query;
			        }
		        });
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see eblog.dao.impl.BaseDao#saveOrUpdate(java.lang.Object)
	 */
	public void saveOrUpdate(Object obj) {
		try {
			this.getHibernateTemplate().saveOrUpdate(obj);
		} catch (DataAccessException e) {
			// log.debug("saveOrUpdate object error!");
			e.printStackTrace();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see eblog.dao.impl.BaseDao#saveOrUpdate(java.util.Collection)
	 */
	public <T> void saveOrUpdate(Collection<T> entities) {
		try {
			this.getHibernateTemplate().saveOrUpdateAll(entities);
		} catch (DataAccessException e) {
			// log.debug("saveOrUpdate object SET error!");
			e.printStackTrace();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see eblog.dao.impl.BaseDao#updateObject(java.lang.Object)
	 */
	public void updateObject(Object obj) throws HibernateException {
		this.getHibernateTemplate().update(obj);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see eblog.dao.impl.BaseDao#saveObject(java.lang.Object)
	 */
	public Serializable saveObject(Object obj) throws HibernateException {
		return this.getHibernateTemplate().save(obj);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see eblog.dao.impl.BaseDao#getObjectById(java.lang.Class,
	 * java.io.Serializable)
	 */
	public <T> T getObjectById(Class<T> class1, Serializable serializable)
	        throws HibernateException {
		return (T) this.getHibernateTemplate().get(class1, serializable);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see eblog.dao.impl.BaseDao#hqlQuery(java.lang.String)
	 */
	public <T> List<T> hqlQuery(String hsql) throws HibernateException {
		return query(hsql, null);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see eblog.dao.impl.BaseDao#hqlQuery(java.lang.String, java.lang.Object)
	 */
	public <T> List<T> hqlQuery(String hsql, Object obj)
	        throws HibernateException {
		return query(hsql, obj);
	}

	@SuppressWarnings("unchecked")
	private <T> List<T> query(final String hsql, final Object obj)
	        throws HibernateException {
		// int count = 0;

		List<T> queryList = (List<T>) getHibernateTemplate().execute(
		        new HibernateCallback<Object>() {
			        public Object doInHibernate(Session session)
			                throws HibernateException, SQLException {
				        Query query = session.createQuery(hsql);

				        if (obj != null) {
					        if (obj instanceof Map) {
						        String as[] = query.getNamedParameters();
						        for (int k1 = 0; k1 < as.length; k1++) {
							        query.setParameter(as[k1],
							                ((Map<T, T>) obj).get(as[k1]));
						        }
					        } else if (obj instanceof Object[]) {
						        for (int i1 = 0; i1 < ((Object[]) obj).length; i1++) {
							        query.setParameter(i1, ((Object[]) obj)[i1]);

						        }
					        } else {
						        query.setParameter(0, obj);
					        }
				        }
				        return query.list();
			        }
		        });

		return queryList;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see eblog.dao.impl.BaseDao#getResultCount(java.lang.String)
	 */
	public int getResultCount(String hql) {
		int count = 0;
		Session session = getSession();
		try {
			Query query = session.createQuery(hql);
			count = query.list().size();
		} catch (Exception e) {
			// log.error("获得记录条数异常！");
			e.printStackTrace();
		} finally {
			session.close();
		}
		return count;
	}

	private String toUpperCaseFirstLetter(String name) {
		return isNullStr(name) ? name : name.substring(0, 1).toUpperCase()
		        + name.substring(1);
	}

	private static boolean isNullStr(String s) {
		return (s == null || s.equals("null") || s.equals("")) ? true : false;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see eblog.dao.impl.BaseDao#queryByPage(java.lang.String, int, int)
	 */
	@SuppressWarnings("unchecked")
	public <T> List<T> queryByPage(String hql, int beginIndex, int pageSize) {
		Session session = this.getSession();
		// Transaction transaction = null;
		try {
			// transaction = session.beginTransaction();
			Query query = session.createQuery(hql);

			List<T> list;
			if (query.list().isEmpty()) {
				list = null;
			} else {
				query.setFirstResult(beginIndex);
				query.setMaxResults(pageSize);
				list = query.list();
			}
			// transaction.commit();
			return list;
		} catch (Exception e) {
		} finally {
			session.close();
		}
		return null;
	}

	// 查询指定HQL的结果记录总数
	private int queryRowCount(final String hql) {
		// Session s
		// ession=HibernateSessionFactory.getSessionFactory().getCurrentSession();
		Session session = this.getSession();
		// Transaction transaction=null;
		try {
			// transaction=session.beginTransaction();
			Query query = session.createQuery(hql);
			int result = query.list().size(); // 计算个数
			// transaction.commit();

			return result;
		} catch (Exception e) {
		} finally {
			session.close();
		}
		return 0;
	}

	

}
